# -*- coding: utf-8 -*-
from __future__ import unicode_literals

import re
import os
import sys
import mimetypes
from datetime import datetime, timedelta
import hashlib

from werkzeug.routing import BaseConverter

from itsdangerous import URLSafeTimedSerializer, URLSafeSerializer

import pytz

try:
    from io import BytesIO as StringIO
except ImportError:
    try:
        from cStringIO import StringIO
    except ImportError:
        from StringIO import StringIO

from PIL import Image

class RegexConverter(BaseConverter):
    def __init__(self, _map, *args):
        self.map = _map
        self.regex = args[0]

def getSplitExt(file_name):
    filetmp = os.path.splitext(file_name)
    file_base = filetmp[0].split('/')[-1]
    file_ext = filetmp[-1].split('.')[-1]
    return (file_base, file_ext)

def getMimeType(file_name):
    mimetypes.init()
    return mimetypes.types_map.get(os.path.splitext(file_name)[-1], None)

def isObjectId(obj_id):
    if not obj_id is None:
        if bytes == str:
            # python 2
            chrs24 = (isinstance(obj_id, bytes) or isinstance(obj_id, str) or isinstance(obj_id, unicode)) and len(obj_id) == 24
            bys12 = isinstance(obj_id, bytearray) and len(ob_id) == 12
        else:
            # python 3
            chrs24 =  isinstance(obj_id, str) and len(obj_id) == 24
            bys12 = (isinstance(obj_id, bytearray) or isinstance(obj_id, bytes)) and len(ob_id) == 12
        if chrs24:
            chrs24 = re.match(r'^[a-fA-F0-9]{24}$', obj_id)
        return chrs24 or bys12
    return False

def getImageMime(img_path):
    f = open(img_path, 'rb')
    raw_content = f.read()
    content = StringIO(raw_content)
    mime = Image.open(content).format.lower()
    f.close()
    return mime

def ensureDT(dt=None, tz=None):
    if tz is None:
        tz = pytz.timezone('Asia/Shanghai')
    if not dt is None and str(dt).isdigit():
        dt = fromTimeStamp(dt, tz)
    if not isinstance(dt, datetime):
        dt = datetime.now(tz)
    return dt

def formatDT(fmt='%Y-%m-%d %H:%M:%S.%f', dt=None, tz=None):
    dt = ensureDT(dt, tz)
    return dt.strftime(fmt)

def fromTimeStamp(timestamp, tz=None):
    '''从时间戳得到datetiem对象'''
    if tz is None:
        tz = pytz.timezone('Asia/Shanghai')
    return datetime.fromtimestamp(timestamp, tz)

def getTimeStamp(dt=None, tz=None):
    '''获取datetime对象的时间戳'''
    dt = ensureDT(dt, tz)
    try:
        timestamp = dt.timestamp()
    except AttributeError:
        import time
        timestamp = time.mktime(dt.timetuple())
    return timestamp

def md5(origin_str):
    m5 = hashlib.md5()
    try:
        m5.update(origin_str)
    except TypeError:
        m5.update(origin_str.encode('utf-8'))
    except UnicodeEncodeError:
        m5.update(origin_str.encode('utf-8'))
    return m5.hexdigest()

def encryptPwd(pwd):
    '''密码加密'''
    m5 = hashlib.md5()
    try:
        m5.update(pwd)
    except TypeError:
        m5.update(pwd.encode('utf-8'))
    except UnicodeEncodeError:
        m5.update(pwd.encode('utf-8'))
    ret = m5.hexdigest()
    begin = 10
    end = 20
    tmp = ret[-1::-1][1::2]
    ret = ret[1::2]
    _str = zip(tmp, ret)
    if sys.version_info.major < 3:
        _str = str(_str)
    else:
        _str = str([i for i in _str])
        _str = bytearray(_str, 'utf-8')
    m5.update(_str)
    return m5.hexdigest()

def create_rand(length):
    '''
    生成随机数(数字)
    length: 随机数长度（位数）
    '''
    from random import Random
    rand = Random()
    ret = []
    while len(ret) < length:
        ret.append(str(rand.randint(0, 9)))
    return ''.join(ret)

def send_forget_pwd_code(mailer, receiver, code):
    '''发送忘记密码的验证码'''
    mailer.send(
        receiver=receiver,
        message=''.join([
            '<div>',
            '验证码:',
            '&nbsp;<strong>',
            code,
            '</strong>',
            '</div>'
        ]),
        subject='密码找回',
        html=True,
        from_msg='密码找回中心',
        to_msg=receiver.split('@')[0]
    )

def generate_confirmation_token(origin_message, secret_key, security_salt):
    '''生成一个token'''
    serializer = URLSafeTimedSerializer(secret_key, salt=security_salt)
    return serializer.dumps(origin_message)

def confirm_token(token, secret_key, security_salt, expiration=3600, exceptLoger=None):
    '''验证token'''
    serializer = URLSafeTimedSerializer(secret_key, salt=security_salt)
    origin_message = None
    try:
        origin_message = serializer.loads(
            token,
            max_age=expiration
        )
    except Exception as ex:
        print(ex)
        if not exceptLoger is None and hasattr(exceptLoger, '__call__'):
            exceptLoger()
    return origin_message

def generate_simple_token(origin_message, secret_key):
    '''生成一个简单token'''
    # http://itsdangerous.readthedocs.io/en/latest/
    print('generate_simple_token:')
    print(secret_key)
    serializer = URLSafeSerializer(secret_key)
    return serializer.dumps(origin_message)

def unsign_simple_token(token, secret_key, exceptLoger=None):
    '''验证token, 解密出原始数据'''
    print('unsign_simple_token:')
    print(secret_key)
    origin_message = None
    try:
        serializer = URLSafeSerializer(secret_key)
        origin_message = serializer.loads(token)
    except Exception as ex:
        if not exceptLoger is None and hasattr(exceptLoger, '__call__'):
            exceptLoger()
    return origin_message

def in_text_range(text, min_len, max_len, _strip=True):
    if bool(text):
        if _strip:
            text = text.strip()
        return min_len <= len(text) <= max_len
    return False

def is_email(email):
    if bool(email):
        pattern = r'^[\w\-]+@[\w]+(([\.][a-zA-Z]+)+)$'
        return bool(re.match(pattern, email))
    return False

def text_required(text, _strip=True):
    if bool(text):
        if _strip:
            text = text.strip()
        return bool(text)
    return False

def read_config(cfg_file, cfg_key):
    '''读取配置文件，适用于整数，浮点数，字符串和字典（支持嵌套字典）'''
    keys = cfg_key.split('.')
    if len(keys) < 1:
        return None
    _property = cfg_file
    _value = None
    if len(keys) > 1:
        _key = keys[0]
        _property = getattr(cfg_file, _key, None)
        _index = 1
        while _index < len(keys):
            if bool(_property):
                _key = keys[_index]
                if type(_property) in [int, str, float]:
                    _property = getattr(_property, _key, None)
                elif isinstance(_property, dict):
                    _key = keys[_index]
                    _property = _property.get(_key, None)
                    _index += 1
            else:
                break
        else:
            _value = _property
    elif len(keys) == 1:
        _value = getattr(cfg_file, keys[0], None)
    return _value

def readDict(_dic, _key):
    keys = _key.split('.')
    if len(keys) < 1:
        return None
    _property = _dic
    _value = None
    if len(keys) > 1:
        _index = 0
        while _index < len(keys):
            if isinstance(_property, dict):
                _key = keys[_index]
                _property = _property.get(_key, None)
                _index += 1
            elif isinstance(_property, list) or isinstance(_property, tuple):
                _key = int(keys[_index])
                _property = _property[_key]
                _index += 1
            else:
                break
        else:
            _value = _property
    elif len(keys) == 1:
        _value = _dic[keys[0]]
    return _value

def ensurePath(path):
    if not os.path.exists(path) or not os.path.isdir(path):
        os.makedirs(path)

def ensureFile(file_path):
    if not os.path.exists(file_path) or not os.path.isfile(file_path):
        f = open(file_path, 'w')
        f.close()

def checkFile(path, err_msg=None):
    if not os.path.exists(path) or not os.path.isfile(path):
        if not err_msg is None:
            print(err_msg)
        else:
            print('error: 文件[{0}]不存在，程序已退出，请修复错误后重试.'.format(path))
        import sys
        sys.exit(1)

def datesInWeek(week=0):
    '''
    获取某一周之内的所有日期
    week 距离当前周多少周(>= 0)
    '''
    if not isinstance(week, int) or week < 0:
        week = 0
    _today = datetime.now()
    _index = _today.weekday() + 1
    _dates = []
    if week == 0:
        _calc_date = _today
        _begin = 0
    else:
        _calc_date = _today -timedelta(days=_index)
        _index = 7 * week
        _begin = _index - 7
    for i in range(_begin, _index):
        _date = _calc_date - timedelta(days=i)
        _date_str = _date.strftime('%Y-%m-%d')
        _dates.append(_date_str)
    return _dates

def real_print(*msgs):
    f = sys._getframe().f_back
    file_name = f.f_code.co_filename
    func_name = f.f_code.co_name
    line_number = f.f_lineno
    print('*' * 80)
    print('file: {0}\nfunc: {1}\nline: {2}'.format(
        file_name,
        func_name,
        line_number
    ))
    for msg in msgs:
        print(msg)
    print()

if __name__ == '__main__':
    '''
    import extra_config
    def _test(_key):
        print('{0}: {1}'.format(
            _key,
            read_config(extra_config, _key)
        ))
    _test('TEST.t1.t11.t111')
    _test('TEST.t1.t12')
    _test('TEST.t2')
    _test('LISTEN_PORT')
    '''
    print(datesInWeek(3))